/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

var osapps = osapps || {};
osapps.model = osapps.model || {};

//Templates for the profile/friend/appData of a person. 
osapps.model.IPersonData = {
  //opensocial.Person
  person : null,
  
  //the data of the person in this app. 
  data : null,
  
  //array of osapps.model.IPersonData
  friends : null,
  
  //iterator the friends
  forEachFriend : function(callback, opt_scope){
    osapps.forEach(this.friends, callback, opt_scope);
  }
};

osapps.model.NotificationType = {
  ALL_UPDATED : "ALL_UPDATED",
  MSG_UPDATED : "MSG_UPDATED"
};

//Templates for a Notification Broadcaster.
osapps.model.NotificationBroadcaster = {
  notificationListeners : {},
  sequence_ : 0,
  
  subscribe : function(notificationType, notificationListener){
    var notificationListenerId = "ln_" + this.sequence_++;
    notificationType = notificationType || osapps.model.NotificationType.ALL_UPDATED;
    this.notificationListeners[notificationType] = this.notificationListeners[notificationType] || {};
    this.notificationListeners[notificationType][notificationListenerId] = notificationListener;
    return notificationListenerId;
  },
  
  unsubscribe : function(notificationType, notificationListenerId){
    notificationType = notificationType || osapps.model.NotificationType.ALL_UPDATED;
    delete this.notificationListeners[notificationType][notificationListenerId];
  },
  
  isSubscribed : function(notificationType, notificationListener){
    if (notificationListener) {
      notificationType = notificationType || osapps.model.NotificationType.ALL_UPDATED;
      if (this.notificationListeners[notificationType]) {
        for (var notificationListenerId in this.notificationListeners[notificationType]) {
          if (this.notificationListeners[notificationListenerId] === notificationListener) {
            return notificationListenerId;
          }
        }
      }
    }
    
    return null;
  },
  
  broadcast : function(notificationType, args){
    notificationType = notificationType || osapps.model.NotificationType.ALL_UPDATED;
    if (notificationType != osapps.model.NotificationType.ALL_UPDATED) {
      callTypedListeners_(notificationType, args);
      callTypedListeners_(osapps.model.NotificationType.ALL_UPDATED, args);
    } else {
      for (var type in this.notificationListeners) {
        this.callTypedListeners_(type, args);
      }
    }
  },
  
  callTypedListeners_ : function(notificationType, args) {
    var typedListeners = this.notificationListeners[notificationType]
    if (typedListeners) {
      for (var notificationListenerId in typedListeners) {
        var notificationListener = typedListeners[notificationListenerId];
        if (notificationListener instanceof Function) {
          notificationListener.call(this, args);
        } else if (notificationListener && (notificationListener.update instanceof Function)){
          notificationListener.update.call(this, args);
        }
      }
    }
  }
};

osapps.model.IApp = {
  //info of contianer, should copied or link to osapps.Loader.environment
  environment : null,

  //osapps.model.IPersonData
  viewer : null,
  
  //a handy flag to show if owner is viewer himself.
  isViewingSelf : true,
  
  //osapps.model.IPersonData 
  owner : null,
  
  //the global data in this app: ranking, notice, etc.
  globalScope : null
};
osapps.mixin(osapps.model.IApp, osapps.model.NotificationBroadcaster);

